package com.bosicloud.cmb.ibp.api.manager.util;

import io.swagger.models.ArrayModel;
import io.swagger.models.Model;
import io.swagger.models.RefModel;
import io.swagger.models.parameters.*;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties
public class SwaggerParameterProperties {

    private String name;
    private String desp;
    private String required;
    private String paramType;
    private String paramIn;

    public static SwaggerParameterProperties buildParameter(AbstractSerializableParameter parameter) {

        return SwaggerParameterProperties.builder()
                .name(parameter.getName())
                .desp(parameter.getDescription())
                .required(convertRequiredBoolean2String(parameter.getRequired()))
                .paramType(parameter.getType())
                .paramIn(parameter.getIn())
                .build();
    }

    private static String convertRequiredBoolean2String(boolean required) {
        return required ? "y" : "n";
    }

    public static List<SwaggerParameterProperties> buildBodyParameters(Map<String, Property> properties) {
        return properties.entrySet()
                .stream()
                .map(e -> fetchBodyProperty(e.getKey(), e.getValue()))
                .collect(Collectors.toList());
    }

    public static SwaggerParameterProperties fetchBodyProperty(String propertyName, Property property) {

        return SwaggerParameterProperties.builder()
                .name(propertyName)
                .paramType(property.getType())
                .required(convertRequiredBoolean2String(property.getRequired()))
                .paramIn("body")
                .build();
    }


    public static List<SwaggerParameterProperties> fetchParameterProperties(Map<String, Model> modelMap, Parameter parameter) {
        List<SwaggerParameterProperties> swaggerParameterProperties = new ArrayList<>();
        if (parameter instanceof BodyParameter) {
            Model model = ((BodyParameter) parameter).getSchema();
            if (model instanceof RefModel) {
                RefModel refModel = (RefModel) model;
                Model simpleRefModel = modelMap.get(refModel.getSimpleRef());
                Map<String, Property> properties = simpleRefModel.getProperties();
                swaggerParameterProperties.addAll(buildBodyParameters(properties));
            }
            if (model instanceof ArrayModel) {
                ArrayModel arrayModel = (ArrayModel) model;
                Property property = arrayModel.getItems();
                if (property instanceof RefProperty) {
                    String simpleRef = ((RefProperty) property).getSimpleRef();
                    Model simpleRefModel = modelMap.get(simpleRef);
                    Map<String, Property> properties = simpleRefModel.getProperties();
                    swaggerParameterProperties.addAll(buildBodyParameters(properties));
                }
            }
        }
        if (parameter instanceof PathParameter) {
            swaggerParameterProperties.add(buildParameter((PathParameter) parameter));
        }

        if (parameter instanceof QueryParameter) {
            QueryParameter queryParameter = (QueryParameter) parameter;
            swaggerParameterProperties.add(buildParameter(queryParameter));
        }

        if (parameter instanceof HeaderParameter) {
            HeaderParameter headerParameter = (HeaderParameter) parameter;
            swaggerParameterProperties.add(buildParameter(headerParameter));
        }
        return swaggerParameterProperties;
    }
}
